qutebrowser ObjectRegistry
In the source code of qutebrowser, there are numerous accesses to the objreg
object, which corresponds to the ObjectRegistry
class. Simply put, it's a singleton manager that facilitates accessing instances conveniently across different parts of the code. What makes it unique is its association with the lifecycle of QObject; when a QObject is released, the instance is automatically removed from the ObjectRegistry
, preventing memory leaks.
This article discusses the following two aspects:
- Implementation Principle
- Usage
Implementation Principle
In Python, a dictionary (Dict) is a commonly used data structure for key-value storage. Python's collections standard library provides a UserDict class specifically for custom dictionary extensions. For usage of UserDict, please click on the note UserDict.
In the ObjectRegistry
class of qutebrowser, a dictionary associated with the lifecycle of QObject is implemented based on UserDict.
When the added object is a QObject instance, the class automatically binds a slot function to the destroyed
signal of the instance. When the instance is destroyed in Qt, it is automatically deleted from the ObjectRegistry dictionary, thus achieving automatic release.
The class signature is as follows:
class ObjectRegistry(collections.UserDict):
Key implementation is as follows.
Binding destroyed Signal
Override the __setitem__
method:
def __setitem__(self,
name: _IndexType,
obj: Any) -> None:
if isinstance(obj, QObject):
func = functools.partial(
self.on_destroyed,
name)
obj.destroyed.connect(func)
self._partial_objs[name] = func
super().__setitem__(name, obj)
Note that this uses Python functools partial, for which you can click the note for reference.
The slot function bound here is on_destroyed
.
on_destroyed
def on_destroyed(self, name: str) -> None:
QTimer.singleShot(
0,
functools.partial(
self._on_destroyed,
name))
def _on_destroyed(self, name: str) -> None:
if not hasattr(self, 'data'):
# ...
return
try:
del self[name]
del self._partial_objs[name]
except KeyError:
pass
It's important to note that the deletion of the instance is not synchronous but is converted to asynchronous execution using QTimer. The reason is that the instances registered need to be used during the synchronous destruction process, so they cannot be immediately deleted.
Usage
objreg.register
Instances are registered to the ObjectRegistry
via the register
method.
In the code, the usage is as follows:
Register a window instance under the name 'last-focused-main-window'
. If an object already exists, it is updated:
objreg.register(
'last-focused-main-window',
window,
update=True)
Register save_manager
as a global instance:
objreg.register(
'save-manager',
save_manager)
In addition to the global singleton, ObjectRegistry
also supports a local Registry. For example, in browsertab, abstractTab registers itself to the local Registry:
objreg.register(
'tab',
self,
registry=self.registry)
ObjectRegistry
also supports different scopes
for hierarchical management of instances, such as a window
scope managing instances under a particular window. This ensures that instances with the same name in different scopes are isolated from each other:
objreg.register(
'mode-manager',
modeman,
scope='window',
window=win_id)
From the examples given, it's evident that ObjectRegistry
is quite flexible and powerful in its functionality. It provides a way to manage instances conveniently across different parts of the application, ensuring that objects are accessible and correctly managed in terms of memory and lifecycle, especially in a complex application like a web browser where multiple components and instances need to interact efficiently.
objreg.get
The ObjectRegistry
's get method is used to obtain an instance.
Get last-focused window:
tabbed_browser = objreg.get(
'tabbed-browser',
scope='window',
window='last-focused')
Get download manager:
download_manager = objreg.get(
'qtnetwork-download-manager')
Get tabbed browser of given window id:
tb = objreg.get(
'tabbed-browser',
scope='window',
window=self._tab.win_id)
本文作者:Maeiee
本文链接:qutebrowser ObjectRegistry
版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!
喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!